package com.gbase8c.dmt.db.oracle;

import com.gbase8c.dmt.db.object.ColumnObject;
import com.gbase8c.dmt.model.migration.dto.ColumnType;
import com.gbase8c.dmt.model.migration.dto.DataSourceDto;
import com.gbase8c.dmt.model.migration.dto.TableDto;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.BeanProcessor;
import org.apache.commons.dbutils.GenerousBeanProcessor;
import org.apache.commons.dbutils.RowProcessor;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;

public class ColumnObjectImpl extends MetaImpl implements ColumnObject {

    public ColumnObjectImpl(DataSourceDto dataSourceDto) {
        super(dataSourceDto);
    }

    @Override
    public List<TableDto.ColumnDto> columnDtos(String schema, String tableName) {
        String sql = "select owner as schema, table_name, column_name as name, data_type, data_length, data_precision, data_scale, nullable from all_tab_columns where owner = ? and table_name = ?";
        BeanProcessor beanProcessor = new GenerousBeanProcessor();
        RowProcessor rowProcessor = new BasicRowProcessor(beanProcessor);
        List<TableDto.ColumnDto> columnDtos = query(sql, new BeanListHandler<>(TableDto.ColumnDto.class, rowProcessor), schema, tableName);
        return columnDtos;
    }

    private List<ColumnType> query(String sql, Object... params) {
        BeanProcessor beanProcessor = new GenerousBeanProcessor();
        RowProcessor rowProcessor = new BasicRowProcessor(beanProcessor);
        List<ColumnType> columnTypes = query(sql, new BeanListHandler<>(ColumnType.class, rowProcessor), params);
        // 对一些映射做处理
        for (ColumnType columnType : columnTypes) {
            columnType.setSqlType(toSqlType(columnType.getDataType()));
//            if ("NUMBER".equalsIgnoreCase(columnType.getDataType())) {
//                if (ObjectUtils.isEmpty(columnType.getDataPrecision())) {
//                    columnType.setDataPrecision(32);
//                }
//                if (ObjectUtils.isEmpty(columnType.getDataScale())) {
//                    columnType.setDataScale(0);
//                }
//            }
        }
        return columnTypes;
    }

    @Override
    // full/include/exclude
    public List<ColumnType> columnTypes(String schema, String type, List<String> tableNames) {
        List<ColumnType> columnTypes = Lists.newArrayList();
        if (StringUtils.isBlank(type) || "full".equalsIgnoreCase(type)) {
            String sql = "select distinct data_type, data_length, data_precision, data_scale from all_tab_columns where owner = ?";
            columnTypes = query(sql, schema);
        } else {
            String sql = null;
            if ("include".equalsIgnoreCase(type)) {
                sql = "select distinct data_type, data_length, data_precision, data_scale from all_tab_columns where owner = ? and table_name in (%s)";
            } else {
                sql = "select distinct data_type, data_length, data_precision, data_scale from all_tab_columns where owner = ? and table_name not in (%s)";
            }

            if (CollectionUtils.isEmpty(tableNames)) {
                columnTypes = query(sql, schema, Lists.newArrayList());
            } else {
                // todo 根据数据库版本动态调整in参数个数
                // 9i及一下 100
                // 9i以上 1000
                int limit = 100;
                int qt = tableNames.size() / limit + (tableNames.size() % limit > 0 ? 1 : 0);
                for (int i=0; i<qt; i++) {
                    List<String> tns = Lists.newArrayList();
                    if (i < qt-1) {
                        tns = tableNames.subList(i * limit, (i + 1) * limit);
                    } else {
                        tns = tableNames.subList(i * limit, tableNames.size());
                    }
                    List<ColumnType> cts = query(sql, schema, tns);
                    columnTypes.addAll(cts);
                }
            }
        }
        return columnTypes;
    }

    @Override
    public ColumnType toColumnType(ColumnType srcColumnType) {
        return null;
    }


    @Override
    public List<String> getNames(Map<String, Object> params) {
        return null;
    }

    @Override
    public TableDto.ColumnDto get(String name, Map<String, Object> params) {
        return null;
    }

    @Override
    public TableDto.ColumnDto convert(TableDto.ColumnDto columnDto, Map<String, Object> params) {
        return null;
    }

    @Override
    public String sql(TableDto.ColumnDto columnDto, Map<String, Object> params) {
        return null;
    }
}
